using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using TD.Interface.Menus;

namespace TD.TheGame
{
    /// <summary>
    /// The age in which the game currently resides.
    /// </summary>
    public enum Age : int
    {
        Future = 0x02,   // Toekomst
        Present = 0x01,  // Heden
        Past = 0x00      // Verleden
    }

    /// <summary>
    /// This is a game component that implements IUpdateable.
    /// </summary
    public class LevelComponent : DrawableGameComponent
    {
        public List<EnemySprite> currentEnemys
        {
            // System.IndexOutOfRangeException, when shooting the last enemy.
            get { return Levels[CurrentLevel].Enemys; }
        }


        public int Points
        {
            get;
            set;
        }

        public Age CurrentAge
        {
            get
            {
                int decade = (CurrentLevel / 5);

                switch (decade)
                {
                    case 1:
                        return Age.Present;

                    case 2:
                        return Age.Future;

                    case 0:
                    default:
                        return Age.Past;
                }
            }
        }

        public int currLevel
        {
            get { return CurrentLevel; }
        }

        bool gameOver = false;
        bool shopping = false;

        SpriteBatch spriteBatch;

        public bool GameOver
        {
            get { return gameOver; }
            set { gameOver = value; }
        }

        // Counter
        int CurrentLevel = 0;

        // Maximum amount of levels
        const int MAXLEVEL = 15;

        // Collection of levels
        Level[] Levels;

        public LevelComponent(Game game)
            : base(game)
        {
            Points = 0;
            // TODO: Construct any child components here
            Levels = new Level[MAXLEVEL];
            Levels[0] = new Level1(Game);
            Levels[1] = new Level2(Game);
            Levels[2]  = new Level3(Game);
            Levels[3] = new Level4(Game);
            Levels[4] = new Level5(Game);
            Levels[5] = new Level6(Game);
            Levels[6] = new Level7(Game);
            Levels[7] = new Level8(Game);
            Levels[8] = new Level9(Game);
            Levels[9] = new Level10(Game);
            Levels[10] = new Level11(Game);
            Levels[11] = new Level12(Game); 
            Levels[12] = new Level13(Game);
            Levels[13] = new Level14(Game);
            Levels[14] = new Level15(Game);
            Levels[0].LvlState = LevelState.Playing;
            spriteBatch = (SpriteBatch)Game.Services.GetService(typeof(SpriteBatch));
        }

        /// <summary>
        /// Allows the game component to perform any initialization it needs to before starting
        /// to run.  This is where it can query for any required services and load content.
        /// </summary>
        public override void Initialize()
        {
            // TODO: Add your initialization code here
            foreach (var level in Levels)
            {
                level.Initialize();
                level.OnFinishedLevel += new FinishedLevel(this.OnFinishedLevel);
            }
            base.Initialize();

            // Ensure the rest has been initialized prior to this!
            ShopMenu shop = (ShopMenu)Game.Services.GetService(typeof(ShopMenu));
            shop.Exit += new Interface.MenuBase.OnExit(this.OnFinishedShopping);
        }

        /// <summary>
        /// Allows the game component to update itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        public override void Update(GameTime gameTime)
        {
            // TODO: Add your update code here
            if (!gameOver && !shopping)
            {
                foreach (var level in Levels)
                {
                    if (level != null && level.LvlState == LevelState.Playing)
                    {
                        level.Update(gameTime);
                        if (level.LvlState == LevelState.GameOver && CurrentLevel < MAXLEVEL)
                        {
                            CurrentLevel++;
                            if (CurrentLevel >= MAXLEVEL)
                            {
                                gameOver = true;
                                CurrentLevel -= 1;
                            }
                            else
                            {
                                Levels[CurrentLevel].LvlState = LevelState.Playing;
                            }
                        }
                    }
                }

                // Check the health of the castle. If the health is below 1 the player lost.
                Castle castle = (Castle)Game.Services.GetService(typeof(Castle));
                if (castle.Health <= 0)
                {
                    gameOver = true;
                }
            }
            base.Update(gameTime);
        }


        public void Reset()
        {
            // NOTE: To reset the game.
            gameOver = false;

            //Reset each level 
            foreach (Level level in Levels)
            {
                //level.Reset();
            }
            //put all stats to 0;
            CurrentLevel = 0;
            //set lvl 1 to playing
            Levels[CurrentLevel].LvlState = LevelState.Playing;
            //points to ZERO
            Points = 0;
        }

        /// <summary>
        /// Draw
        /// </summary>
        /// <param name="gameTime"></param>
        public override void Draw(GameTime gameTime)
        {
            foreach (var level in Levels)
            {
                level.Draw(gameTime);
            }
        }

        /// <summary>
        /// Called when a level has been finished.
        /// </summary>
        /// <param name="level">The level that has been finished.</param>
        private void OnFinishedLevel(Level level)
        {
            // Ensure the code does not continue till we are done shopping.
            shopping = true;

            // Open up the shop.
            ShopMenu shop = (ShopMenu)Game.Services.GetService(typeof(ShopMenu));
            shop.Enabled = true;
            shop.Visible = true;
        }

        /// <summary>
        /// Called when the player leaves the shop.
        /// </summary>
        /// <param name="sender">The shop menu.</param>
        private void OnFinishedShopping(object sender)
        {
            // Continue the game.
            shopping = false;
        }
    }
}
